
package com.superhelper.printer.task;

import java.util.Date;

import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.superhelper.common.domain.Task;
import com.superhelper.common.mapper.TaskMapper;

public abstract class AbstractTaskRunnable implements Runnable {
    protected Logger log = LoggerFactory.getLogger(this.getClass());
    protected Task task;

    public static int SUCCESS = 0, FAIL = -1;
    @Autowired
    protected TaskMapper taskMapper;

    /**
     * 任务执行前的处理,如果返回true，则可以继续逻辑处理
     * 
     * @return
     */
    protected boolean preExecute() {
        // occupy task
        // int updateResult = taskMapper.occupyTask(task.getId(),
        // task.getRetryTimes());
        // if (updateResult != 1) {
        // log.info("task occuppied by other thread, task stopped!");
        // return false;
        // }
        return true;
    }

    /**
     * 业务逻辑执行，如果执行成功，不需要后续处理则返回0;如果需要后续处理（如：需要重试），则返回-1,其他的就是延迟时间分钟数
     */
    protected abstract int execute();

    @Override
    public void run() {
        if (!preExecute()) {
            return;
        }
        int exeResult = execute();
        if (exeResult == 0) {
            taskMapper.deleteTask(task.getId());
            return;
        }
        postExecute(exeResult);
    }

    public void setTask(Task task) {
        this.task = task;
    }

    /**
     * 任务的后续处理
     */
    protected void postExecute(int minutes) {
        if (task.getRetryTimes() >= 10) {
            log.warn("execute failed, task={}", task);
            return;// 暂时不删除这样情况的任务，方便观察这种情况发生的概率
        }
        Date nextTime = new Date();
        if (minutes == 0) {
            // 10次，Interval为30秒时，各次间隔：1：30秒，2：4分钟，3：13分钟，4：32分钟，5：62分钟，6：108分钟，7：2小时，8：4小时，9：6小时，10：8小时，总共时长：25小时
            int delayLen = (int) Math.pow(task.getRetryTimes(), 2) * 15;
            nextTime = DateUtils.addSeconds(nextTime, delayLen);
        } else {
            nextTime = DateUtils.addMinutes(nextTime, minutes);
        }
        taskMapper.delayTask(task.getId(), nextTime);
    }

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            System.out.println(Math.pow(i, 2) * 15 / 60);
        }
    }
}
